using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;

namespace WMOSSExperts.Helper
{
    public class webConfigEditor
    {

        private SPWebApplication _webApp;
        private Boolean _bTransactionnel;
        private List<SPWebConfigModification> _lstAddModifications;
        private List<SPWebConfigModification> _lstRemoveModifications;

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="WebApp"></param>
        public webConfigEditor(SPWebApplication WebApp)
        {
            if (WebApp == null)
                throw new SPException("WebApp cannot be null in the webConfigEditor constructor");

            _webApp = WebApp;
            _bTransactionnel = false;
            _lstAddModifications = new List<SPWebConfigModification>();
            _lstRemoveModifications = new List<SPWebConfigModification>();

        }

        #region "Manage saving modifications in the web config files"
        /// <summary>
        /// Specify that modifications wait to be executed on the farm servers
        /// </summary>
        public void BeginTrans()
        {
            _bTransactionnel = true;
        }

        /// <summary>
        /// Write the modifications into the web config files on the farm servers
        /// </summary>
        public void Commit()
        {
            this.Save();
            _lstAddModifications.Clear();
            _lstRemoveModifications.Clear();
            _bTransactionnel = false;
        }

        /// <summary>
        /// Removes waiting modifications
        /// </summary>
        public void RollBack()
        {
            _lstAddModifications.Clear();
            _lstRemoveModifications.Clear();
            _bTransactionnel = false;
        }

        /// <summary>
        /// Write modifications into the web config files
        /// </summary>
        public void Save()
        {
            //Add the modifications
            foreach (SPWebConfigModification oModification in _lstAddModifications)
            {
                _webApp.WebConfigModifications.Add(oModification);
            }

            //Remove modifications
            foreach (SPWebConfigModification oModification in _lstRemoveModifications)
            {
                _webApp.WebConfigModifications.Remove(oModification);
            }

            //Apply modifications in all servers for the web application
            _webApp.Farm.Services.GetValue<SPWebService>().ApplyWebConfigModifications();
            _webApp.Update();
        }
        #endregion

        #region "Manage removing modification"
        /// <summary>
        /// Remove attributes modifications in the web.config file and apply modifications
        /// </summary>
        /// <param name="UniqueOwner"></param>
        /// <param name="AttributeName"></param>
        /// <param name="Path"></param>
        /// <returns></returns>
        public Boolean RemoveModification(String UniqueOwner, String AttributeName, String Path)
        {
            return this.RemoveModification(UniqueOwner, AttributeName, Path, true);
        }

        /// <summary>
        /// Remove attributes modifications in the web.config file
        /// </summary>
        /// <param name="UniqueOwner"></param>
        /// <param name="AttributeName"></param>
        /// <param name="Path"></param>
        /// <param name="ApplyModification"></param>
        /// <returns></returns>
        public Boolean RemoveModification(String UniqueOwner, String AttributeName, String Path, Boolean ApplyModification)
        {
            if (String.IsNullOrEmpty(UniqueOwner) | String.IsNullOrEmpty(AttributeName) | String.IsNullOrEmpty(Path))
            {
                //TODO write warning and manage error message
                return false;
            }


            Boolean bFind = false;
            foreach (SPWebConfigModification oModification in _webApp.WebConfigModifications)
            {
                if (oModification.Name == AttributeName & oModification.Path == Path & oModification.Owner == UniqueOwner)
                {
                    _lstRemoveModifications.Add(oModification);
                    bFind = true;
                    break;
                }
            }

            if (!bFind) return false;

            if (ApplyModification)
                this.Commit();

            return true;
        }

        /// <summary>
        /// Remove all modifications from the web.config file according to the originator
        /// </summary>
        /// <param name="UniqueOwner"></param>
        /// <returns></returns>
        public Boolean RemoveAll(String UniqueOwner)
        {
            if (_bTransactionnel)
            {
                throw new SPException("this method can not be called into a transaction");
            }

            foreach (SPWebConfigModification oModification in _webApp.WebConfigModifications)
            {
                if (oModification.Owner == UniqueOwner)
                    _lstRemoveModifications.Add(oModification);
            }

            if (_lstRemoveModifications.Count == 0)
            {
                //TODO Add warning and message about the removeall
                return false;
            }

            this.Commit();
            return true;
        }

        #endregion

        #region "Core add modification"

        /// <summary>
        /// Add modification in the web.config file
        /// </summary>
        /// <param name="UniqueOwner"></param>
        /// <param name="AttributeName"></param>
        /// <param name="Path"></param>
        /// <param name="Value"></param>
        /// <param name="ApplyModification"></param>
        /// <returns></returns>
        public Boolean AddModification(String UniqueOwner, String Name, String Path, String Value, SPWebConfigModification.SPWebConfigModificationType ModificationType, Boolean ApplyModification)
        {

            if (String.IsNullOrEmpty(UniqueOwner) | String.IsNullOrEmpty(Name) | String.IsNullOrEmpty(Path))
            {
                //TODO write warning and manage error message
                return false;
            }

            SPWebConfigModification modification = new SPWebConfigModification(Name, Path);
            modification.Owner = UniqueOwner;
            modification.Sequence = 0;
            modification.Type = ModificationType;
            modification.Value = Value;

            _lstAddModifications.Add(modification);

            if (ApplyModification)
                this.Commit();

            return true;
        }


        #endregion

        #region "Attributes modifications"

        /// <summary>
        /// Add attribute modification in the web.config files
        /// </summary>
        /// <param name="UniqueOwner"></param>
        /// <param name="AttributeName"></param>
        /// <param name="Path"></param>
        /// <param name="Value"></param>
        /// <returns></returns>
        public Boolean AddAttributeModification(String UniqueOwner, String AttributeName, String Path, String Value)
        {
            return this.AddAttributeModification(UniqueOwner, AttributeName, Path, Value, true);
        }

        /// <summary>
        /// Add attribute modification in the web.config file
        /// </summary>
        /// <param name="UniqueOwner"></param>
        /// <param name="AttributeName"></param>
        /// <param name="Path"></param>
        /// <param name="Value"></param>
        /// <param name="ApplyModification"></param>
        /// <returns></returns>
        public Boolean AddAttributeModification(String UniqueOwner, String AttributeName, String Path, String Value, Boolean ApplyModification)
        {
            return this.AddModification(UniqueOwner, AttributeName, Path, Value, SPWebConfigModification.SPWebConfigModificationType.EnsureAttribute, ApplyModification);
        }

        #endregion

        #region "Child nodes modification"

        /// <summary>
        /// Add ChildNode modification in the web.config file
        /// </summary>
        /// <param name="UniqueOwner"></param>
        /// <param name="AttributeName"></param>
        /// <param name="Path"></param>
        /// <param name="Value"></param>
        /// <returns></returns>
        public Boolean AddChildNodeModification(String UniqueOwner, String ChildName, String Path, String Value)
        {
            return this.AddChildNodeModification(UniqueOwner, ChildName, Path, Value, true);
        }

        
        /// <summary>
        /// Add ChildNode modification in the web.config file
        /// </summary>
        /// <param name="UniqueOwner"></param>
        /// <param name="AttributeName"></param>
        /// <param name="Path"></param>
        /// <param name="Value"></param>
        /// <param name="ApplyModification"></param>
        /// <returns></returns>
        public Boolean AddChildNodeModification(String UniqueOwner, String ChildName, String Path, String Value, Boolean ApplyModification)
        {
            return this.AddModification(UniqueOwner, ChildName, Path, Value, SPWebConfigModification.SPWebConfigModificationType.EnsureChildNode, ApplyModification);
        }

        #endregion 

    }
}
